﻿using System.Windows;
using System.Windows.Navigation;
using FanaticRock.Theme.Helpers;

namespace FanaticRock.Theme.Utils
{
    public class NavigateHistorty
    {
        public Uri Uri { get; set; }
        public object ExtraData { get; set; }
    }

    ///<summary>拓展导航服务，里面存储有导航对象。</summary>
    public class ExtendNavigationService
    {
        private const bool EnableCache = false;

        private NavigationService _navigationService;

        private Stack<NavigateHistorty> _backStack = new Stack<NavigateHistorty>();

        [Obsolete("取消了往后翻页", true)]
        private Stack<NavigateHistorty> _forwardStack = new Stack<NavigateHistorty>();

        // Uri 缓存。
        private Dictionary<Uri, FrameworkElement> _cachedUriContent = new Dictionary<Uri, FrameworkElement>();

        public NavigationService NavigationService => _navigationService;

        public ExtendNavigationService(NavigationService navigationService)
        {
            _navigationService = navigationService;
        }

        public void NavigateBack()
        {
            _backStack.TryPop(out var poped);
            //if (poped != null)
            //    _forwardStack.Push(poped);
            _backStack.TryPeek(out var previous);
            if (previous != null)
                NavigateCore(_navigationService, previous.Uri, previous.ExtraData);
        }

        //public void NavigateForward()
        //{
        //    _forwardStack.TryPop(out var poped);
        //    if (poped != null)
        //    {
        //        _backStack.Push(poped);
        //        NavigateCore(_navigationService, poped.Uri, poped.ExtraData);
        //    }

        //}

        public void Navigate(Uri hyperlink, object extraData)
        {
            Navigate(_navigationService, hyperlink, extraData);

        }

        public void Navigate(NavigationService? navigationService, Uri hyperlink, object extraData)
        {
            _backStack.TryPeek(out var previousHyperlink);
            if (Uri.Equals(previousHyperlink, hyperlink))
            {
                // nothing
            }
            else
            {
                _backStack.Push(new NavigateHistorty() { Uri = hyperlink, ExtraData = extraData });
                //_forwardStack.Clear();
                NavigateCore(navigationService, hyperlink, extraData);
            }

        }

        private void NavigateCore(NavigationService? navigationService, Uri hyperlink, object extraData)
        {
            if (hyperlink == null) return;
            if (extraData == null)
            {
                if(EnableCache)
                {
                    if (_cachedUriContent.TryGetValue(hyperlink, out var content))
                    {
                        navigationService.Navigate(content);
                    }
                    else
                    {
                        navigationService.Navigate(hyperlink);
                    }
                }
                else
                {
                    navigationService.Navigate(hyperlink);
                }
              
            }
            else
            {
                navigationService.Navigate(hyperlink, extraData);
            }

            GC.Collect();
        }

        public void CacheIt(Uri uri, FrameworkElement uiElement)
        {
            var isNavigateCached = NavigationHelper.GetIsNavigateCached(uiElement);
            if (isNavigateCached == true && uri != null)
            {
                if (_cachedUriContent.ContainsKey(uri) == false)
                {
                    _cachedUriContent.Add(uri, uiElement);
                }
            }
        }

        public Uri GetUriByContent(FrameworkElement content)
        {
            if (content == null) return null;
            var result = _cachedUriContent.FirstOrDefault(i => i.Value == content);
            return result.Key;
        }
    }

    public static class ExtendNavigationServices
    {
        private static Dictionary<NavigationService, ExtendNavigationService> _cache = new Dictionary<NavigationService, ExtendNavigationService>();

        public static ExtendNavigationService GetExtendNavigationService(NavigationService navigationService)
        {
            if (navigationService == null) return null;
            if (_cache.TryGetValue(navigationService, out var extendNavigationService))
            {
                return extendNavigationService;
            }
            else
            {
                extendNavigationService = new ExtendNavigationService(navigationService);
                _cache.Add(navigationService, extendNavigationService);
                return extendNavigationService;
            }
        }
    }
}
